<?php

/**
 * This is the model class for table "license".
 *
 * The followings are the available columns in table 'license':
 * @property string $id_license
 * @property integer $id_user
 * @property string $licensekey
 * @property string $localkey
 * @property string $message
 * @property string $status
 * @property string $registeredname
 * @property string $companyname
 * @property string $email
 * @property integer $serviceid
 * @property integer $productid
 * @property string $productname
 * @property string $regdate
 * @property string $nextduedate
 * @property string $billingcycle
 * @property string $configoptions
 * @property string $md5hash
 * @property string $checkdate
 */
class License extends CActiveRecord
{
	/**
	 * Returns the static model of the specified AR class.
	 * @param string $className active record class name.
	 * @return License the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return 'license';
	}

	/**
	 * @return array validation rules for model attributes.
	 */
	public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array('id_user, serviceid, productid', 'numerical', 'integerOnly'=>true),
			array('licensekey, registeredname, companyname, email, productname, billingcycle, configoptions', 'length', 'max'=>100),
			array('status', 'length', 'max'=>20),
			array('md5hash', 'length', 'max'=>300),
			array('localkey, message, regdate, nextduedate, checkdate', 'safe'),
			// The following rule is used by search().
			// Please remove those attributes that should not be searched.
			array('id_license, id_user, licensekey, localkey, message, status, registeredname, companyname, email, serviceid, productid, productname, regdate, nextduedate, billingcycle, configoptions, md5hash, checkdate', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * @return array relational rules.
	 */
	public function relations()
	{
		// NOTE: you may need to adjust the relation name and the related
		// class name for the relations automatically generated below.
		return array(
		);
	}

	/**
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id_license' => 'Id License',
			'id_user' => 'Id User',
			'licensekey' => 'Licensekey',
			'localkey' => 'Localkey',
			'message' => 'Message',
			'status' => 'Status',
			'registeredname' => 'Registeredname',
			'companyname' => 'Companyname',
			'email' => 'Email',
			'serviceid' => 'Serviceid',
			'productid' => 'Productid',
			'productname' => 'Productname',
			'regdate' => 'Regdate',
			'nextduedate' => 'Nextduedate',
			'billingcycle' => 'Billingcycle',
			'configoptions' => 'Configoptions',
			'md5hash' => 'Md5hash',
			'checkdate' => 'Checkdate',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions.
	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
	 */
	public function search()
	{
		// Warning: Please modify the following code to remove attributes that
		// should not be searched.

		$criteria=new CDbCriteria;

		$criteria->compare('id_license',$this->id_license,true);
		$criteria->compare('id_user',$this->id_user);
		$criteria->compare('licensekey',$this->licensekey,true);
		$criteria->compare('localkey',$this->localkey,true);
		$criteria->compare('message',$this->message,true);
		$criteria->compare('status',$this->status,true);
		$criteria->compare('registeredname',$this->registeredname,true);
		$criteria->compare('companyname',$this->companyname,true);
		$criteria->compare('email',$this->email,true);
		$criteria->compare('serviceid',$this->serviceid);
		$criteria->compare('productid',$this->productid);
		$criteria->compare('productname',$this->productname,true);
		$criteria->compare('regdate',$this->regdate,true);
		$criteria->compare('nextduedate',$this->nextduedate,true);
		$criteria->compare('billingcycle',$this->billingcycle,true);
		$criteria->compare('configoptions',$this->configoptions,true);
		$criteria->compare('md5hash',$this->md5hash,true);
		$criteria->compare('checkdate',$this->checkdate,true);

		return new CActiveDataProvider($this, array(
			'criteria'=>$criteria,
		));
	}
	
	public function check_license($licensekey = null, $localkey = null) {
		$licensekey = is_null($licensekey)? self::TEST_LICENSEKEY : $licensekey;
		$localkey = is_null($localkey)? self::TEST_LOCALKEY : $localkey;
		
	    $whmcsurl = "http://www.__whatever__.com/members/";
	    $licensing_secret_key = "0Bx13Mwa2"; # Unique value, should match what is set in the product configuration for MD5 Hash Verification
	    $check_token = time().md5(mt_rand(1000000000,9999999999).$licensekey);
	    $checkdate = date("Ymd"); # Current date
	    $usersip = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER['LOCAL_ADDR'];
	    $localkeydays = 15; # How long the local key is valid for in between remote checks
	    $allowcheckfaildays = 5; # How many days to allow after local key expiry before blocking access if connection cannot be made
	    $localkeyvalid = false;
	    if ($localkey) {
	        $localkey = str_replace("\n",'',$localkey); # Remove the line breaks
			$localdata = substr($localkey,0,strlen($localkey)-32); # Extract License Data
			$md5hash = substr($localkey,strlen($localkey)-32); # Extract MD5 Hash
	        if ($md5hash==md5($localdata.$licensing_secret_key)) {
	            $localdata = strrev($localdata); # Reverse the string
	    		$md5hash = substr($localdata,0,32); # Extract MD5 Hash
	    		$localdata = substr($localdata,32); # Extract License Data
	    		$localdata = base64_decode($localdata);
	    		$localkeyresults = unserialize($localdata);
	            $originalcheckdate = $localkeyresults["checkdate"];
	            if($localkeyresults['status'] == 'Active'){
		            if ($md5hash==md5($originalcheckdate.$licensing_secret_key)) {
		                $localexpiry = date("Ymd",mktime(0,0,0,date("m"),date("d")-$localkeydays,date("Y")));
		                if ($originalcheckdate>$localexpiry) {
		                    $localkeyvalid = true;
		                    $results = $localkeyresults;
		                    $validdomains = explode(",",$results["validdomain"]);
		                    $validips = explode(",",$results["validip"]);
		                    if (!in_array($_SERVER['SERVER_NAME'], $validdomains)) {
		                        $localkeyvalid = false;
		                        $localkeyresults["status"] = "Invalid";
		                        $results = array();
		                    }else if (!in_array($usersip, $validips)) {
		                        $localkeyvalid = false;
		                        $localkeyresults["status"] = "Invalid";
		                        $results = array();
		                    }else if (@$results["validdirectory"]!=dirname(__FILE__)) {
		                        $localkeyvalid = false;
		                        $localkeyresults["status"] = "Invalid";
		                        $results = array();
		                    }
		                }
		            }
	        	}
	        }
	    }
	    if (!$localkeyvalid) {
	        $postfields["licensekey"] = $licensekey;
//	        $postfields["domain"] = $_SERVER['SERVER_NAME'];
			$postfields["domain"] = '208.43.200.22';
//	        $postfields["ip"] = $usersip;
			$postfields["ip"] = '208.43.200.22';
	        $postfields["dir"] = dirname(__FILE__);
	        if ($check_token) $postfields["check_token"] = $check_token;
	        if (function_exists("curl_exec")) {
	            $ch = curl_init();
	            curl_setopt($ch, CURLOPT_URL, $whmcsurl."modules/servers/licensing/verify.php");
	            curl_setopt($ch, CURLOPT_POST, 1);
	            curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
	            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
	            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	            $data = curl_exec($ch);
	            curl_close($ch);
	        } else {
	            $fp = fsockopen($whmcsurl, 80, $errno, $errstr, 5);
		        if ($fp) {
	        		$querystring = "";
	                foreach ($postfields AS $k=>$v) {
	                    $querystring .= "$k=".urlencode($v)."&";
	                }
	                $header="POST ".$whmcsurl."modules/servers/licensing/verify.php HTTP/1.0\r\n";
	        		$header.="Host: ".$whmcsurl."\r\n";
	        		$header.="Content-type: application/x-www-form-urlencoded\r\n";
	        		$header.="Content-length: ".@strlen($querystring)."\r\n";
	        		$header.="Connection: close\r\n\r\n";
	        		$header.=$querystring;
	        		$data="";
	        		@stream_set_timeout($fp, 20);
	        		@fputs($fp, $header);
	        		$status = @socket_get_status($fp);
	        		while (!@feof($fp)&&$status) {
	        		    $data .= @fgets($fp, 1024);
	        			$status = @socket_get_status($fp);
	        		}
	        		@fclose ($fp);
	            }
	        }
	        if (!$data) {
	            $localexpiry = date("Ymd",mktime(0,0,0,date("m"),date("d")-($localkeydays+$allowcheckfaildays),date("Y")));
	            if ($originalcheckdate>$localexpiry) {
	                $results = $localkeyresults;
	            } else {
	                $results["status"] = "Invalid";
	                $results["description"] = "Remote Check Failed";
	                return $results;
	            }
	        } else {
	            preg_match_all('/<(.*?)>([^<]+)<\/\\1>/i', $data, $matches);
	            $results = array();
	            foreach ($matches[1] AS $k=>$v) {
	                $results[$v] = $matches[2][$k];
	            }
	        }
	        if (isset($results["md5hash"])) {
	            if ($results["md5hash"]!=md5($licensing_secret_key.$check_token)) {
	                $results["status"] = "Invalid";
	                $results["description"] = "MD5 Checksum Verification Failed";
	                return $results;
	            }
	        }
//	        if ($results["status"]=="Active") {
				$results["checkdate"] = $checkdate;
	            $data_encoded = serialize($results);
	            $data_encoded = base64_encode($data_encoded);
	            $data_encoded = md5($checkdate.$licensing_secret_key).$data_encoded;
	            $data_encoded = strrev($data_encoded);
	            $data_encoded = $data_encoded.md5($data_encoded.$licensing_secret_key);
	            $data_encoded = wordwrap($data_encoded,80,"\n",true);
	            $results["localkey"] = $data_encoded;
//	        }
	        $results["remotecheck"] = true;
	    }
        $results["licensekey"] = $licensekey;
	    unset($postfields,$data,$matches,$whmcsurl,$licensing_secret_key,$checkdate,$usersip,$localkeydays,$allowcheckfaildays,$md5hash);
	    return $results;
	}
	
	public function getLast($id_user = null)
	{
		$id_user = is_null($id_user)? app()->user->getData('id_user') : $id_user;
		
		$criteria = new CDbCriteria;
		$criteria->limit = 1;
		$criteria->order = 'id_license DESC';
		//$criteria->addCondition("$id_user='{$id_user}'");
		return $this->find($criteria);
	}
	
	const TEST_LICENSEKEY = 'PStandard-f8f74da23e';
	const TEST_LOCALKEY = '=03OigTMyAzMxAjMioDO6M3OiUGdhR2ajVGajJiO5ozc7IiM2ETZiFWOjdDNzQDOhlzY0gTN4kjNyYjY
0AjZ4YzMkJiOyMjOztjIoNXYoVDZtJiO3ozc7ISP5hGd1FkI6YjOztjIz52bpRHcvdWam52bjJiOzEjO
ztjI0NXZ09CbtRHafNWasJWdw9SbodXa0xWdt9SZt9GavIiOxMjOztjI5J3b0NWZylGZklGbhZnI6QTM
6M3OiYzMy4yM04yM04COwIjI6MTM6M3OiAXaklGbhZnI6cjOztjIt92Yu0Ga3lGdsVXbuc3d3xSbvNmL
th2dpRHb11mI6kjM6M3Oi4Wah12bkRWasFmdioTMxozc7ISZtlGVgUmbPJiO4ozc7ISZsNWejdmbpxGb
pJmI6ITM6M3OiADMtADMtADMwAjI6ATM6M3OiUGdhRWZ1RGd4VmbioTMxozc7ICOx0iMw0yMxAjMioDM
xozc7ISZ0FGZnVmciozN6M3OikCZl52dPhCIkJXYk5WY0NFIuAlI6kTM6M3OiUWbh5GdjVHZvJHcioTM
xozc7IyMioTM6M3OiQWa0NWdk9mcwJiO5ozc7IiMioTM6M3OiQWalNWa2JXZzJiO5ozc7ISbvNmLslWY
tdGQ0EDOltmchx2YzJiOwIjOztjIslWYtVmI6UjOztjIj5WSgM3alV2UioTO6M3OiUWbh5WeuFGct92Y
ioTMxozc7ISZrJXYsNEIuVmdlR3UiozMxozc7ISZtFmbkVmclR3cpdWZyJiO0EjOztjIlZXa0NWQiojN
6M3OiMXd0FGdzJiO2ozc7pjNxoTYa78983da2a9b31ad7f0e912b5030a08e9128c33dd51c43d642dc
eec106101f2c';
}